package com.compasudea.polla.persistencia.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

import com.compasudea.polla.negocio.dto.EquipoDTO;
import com.compasudea.polla.negocio.dto.PartidoDTO;
import com.compasudea.polla.negocio.dto.ResultadoDTO;
import com.compasudea.polla.negocio.dto.UsuarioDTO;
import com.compasudea.polla.util.ConexionBD;

public class DatabasePartidoDAO implements PartidoDAO {


	public Collection<PartidoDTO> getPartidosPorGrupo(String grupo) {
		
		ConexionBD adminConexiones = new ConexionBD();
		Connection con = adminConexiones.getConexion();
		
		Map<String, PartidoDTO> mapa = new HashMap<String, PartidoDTO>();
		Collection<PartidoDTO> resultado = new ArrayList<PartidoDTO>();
		
		ArrayList<String> listaIdPartido = new ArrayList<String>();
		
		ResourceBundle imagenesBundle = ResourceBundle.getBundle("propiedades.imagenes");
		
		PartidoDTO partido = null;
		EquipoDTO equipo = null;
		

	    PreparedStatement pstmt = null;
	    ResultSet rs = null;
	    
	    StringBuffer query = new StringBuffer("SELECT E.ID_EQUIPO, E.NOMBRE_EQUIPO, E.GRUPO, E.PJUGADOS,");
	    query.append(" E.PGANADOS, E.PEMPATADOS, E.PPERDIDOS, E.GFAVOR, E.GCONTRA, E.PUNTOS,");
	    query.append(" P.ID_PARTIDO, P.FASES_IDFASE, P.FECHA_LIMITE,");
	    query.append(" EP.SN_LOCAL");
		query.append(" FROM PARTIDOS P");
		query.append(" JOIN EQUIPOS_HAS_PARTIDOS EP ON P.ID_PARTIDO = EP.PARTIDOS_ID_PARTIDO"); 
		query.append(" AND P.FASES_IDFASE = EP.PARTIDOS_FASES_IDFASE");
		query.append(" JOIN EQUIPOS E ON EP.EQUIPOS_ID_EQUIPO = E.ID_EQUIPO");
		
		if (grupo != null) {
			query.append(" WHERE E.GRUPO = ?");
		}
		
		query.append(" ORDER BY ID_PARTIDO, SN_LOCAL DESC");
	   
	    
	    try {
	    	
	      pstmt = con.prepareStatement(query.toString());
	      
	      if (grupo != null) {
	    	  pstmt.setString(1, grupo);
	      }
	      
	      rs = pstmt.executeQuery();
	      
	      while (rs.next()) {
	    	  
	    	  partido = mapa.remove(Integer.toString(rs.getInt("ID_PARTIDO")));
	    	  
	    	  //si no lo encuentra en el mapa
	    	  if (partido == null) {
	    		  
		    	  partido = new PartidoDTO();
		    	  //arma la informacion del partido.
		    	  partido.setIdPartido(rs.getInt("ID_PARTIDO"));
		    	  partido.setIdFase(rs.getInt("FASES_IDFASE"));
		    	  partido.setFechaLimite(rs.getDate("FECHA_LIMITE"));
		    	  
		    	  listaIdPartido.add(Integer.toString(partido.getIdPartido()));
	    	  }
	    	  
	    	  //obtiene la informacion de los equipos.
	    	  equipo = new EquipoDTO();
	    	  equipo.setIdEquipo(rs.getInt("ID_EQUIPO"));
	    	  equipo.setNombre(rs.getString("NOMBRE_EQUIPO"));
	    	  equipo.setBandera(imagenesBundle.getString((equipo.getNombre()).replace(" ", "_")));
	    	  equipo.setGrupo(rs.getString("GRUPO"));
	    	  equipo.setPj(rs.getInt("PJUGADOS"));
	    	  equipo.setPg(rs.getInt("PGANADOS"));
	    	  equipo.setPe(rs.getInt("PEMPATADOS"));
	    	  equipo.setPp(rs.getInt("PPERDIDOS"));
	    	  equipo.setGf(rs.getInt("GFAVOR"));
	    	  equipo.setGc(rs.getInt("GCONTRA"));
	    	  equipo.setPuntos(rs.getInt("PUNTOS"));	    	  
	    	  
	    	  if (rs.getString("SN_LOCAL").equals("S")) {
	    		  partido.setEquipo1(equipo);
	    	  } else {
	    		  partido.setEquipo2(equipo);
	    	  }
	    	  
	    	  mapa.put(Integer.toString(partido.getIdPartido()), partido);	    	  
	      }	      
	      
	    } catch (SQLException e) {
	      e.printStackTrace();
	      
	    } finally { 
	    	
	    	//libera todos los recursos.
	    	try {
		    	
		    	if (pstmt != null) {
		    		pstmt.close();
		    	}
		    	
		    	if (rs != null) {
		    		rs.close();
		    	}
				
			} catch (SQLException e) {
				e.printStackTrace();
			}					      
	    }	    
	    
	    for (String id : listaIdPartido) {
	    	
	    	resultado.add(mapa.remove(id));
	    }

	    return resultado;
	}
	
	/**
	 * Permite obtener el resultado asociado a un partido para un participante.
	 * @param partido Partido del que se desea buscar el resultado.
	 * @param user Usuario en sesion.
	 * @return Resultado en caso de que ya haya sido registrado.
	 */
	public ResultadoDTO getResultado(PartidoDTO partido, UsuarioDTO user) {
		
		ResultadoDTO resultado = null;
		ConexionBD adminConexiones = new ConexionBD();
		Connection con = adminConexiones.getConexion();				
		
	    PreparedStatement pstmt = null;
	    ResultSet rs = null;
	    
	    StringBuffer query = new StringBuffer("SELECT R.PARTIDOS_ID_PARTIDO, R.USUARIOS_DSUSER, ");
	    query.append(" R.PARTIDOS_FASES_IDFASE, R.GOLES_LOCALPENAL, R.GOLES_LOCAL,");
	    query.append(" R.GOLES_VISITANTE, R.GOLES_VISITANTEPENAL, R.PUNTOS_MARCADOR, R.PUNTOS_RESULTADO");
	    query.append(" FROM RESULTADOS R");
	    query.append(" WHERE R.USUARIOS_DSUSER = ?");
	    query.append(" AND R.PARTIDOS_ID_PARTIDO = ?");
	    query.append(" AND R.PARTIDOS_FASES_IDFASE = ?");
	    
	    try {
		    pstmt = con.prepareStatement(query.toString());
		      
		    pstmt.setString(1, user.getIdUser());
		    pstmt.setInt(2, partido.getIdPartido());
		    pstmt.setInt(3, partido.getIdFase());
		    
		    rs = pstmt.executeQuery();
		      
			while (rs.next()) {
				//obtiene la informacion de los equipos.
				resultado = new ResultadoDTO();
				resultado.setIdPartido(rs.getInt("PARTIDOS_ID_PARTIDO"));
				resultado.setIdFase(rs.getInt("PARTIDOS_FASES_IDFASE"));
				resultado.setIdUsuario(rs.getString("USUARIOS_DSUSER"));
				resultado.setGolesLocal(rs.getInt("GOLES_LOCAL"));
				resultado.setGolesVisitante(rs.getInt("GOLES_VISITANTE"));
				resultado.setGolesLocalPenal(rs.getInt("GOLES_LOCALPENAL"));
				resultado.setGolesVisitantePenal(rs.getInt("GOLES_VISITANTEPENAL"));
				resultado.setPuntosMarcador(rs.getInt("PUNTOS_MARCADOR"));
				resultado.setPuntosResultado(rs.getInt("PUNTOS_RESULTADO"));
				resultado.setGuardado(true);
			}
	    
	    } catch (SQLException e) {
	    	e.printStackTrace();
			  
		} finally { 
				
			//libera todos los recursos.
			try {
				
				if (pstmt != null) {
					pstmt.close();
				}
				
				if (rs != null) {
		    		rs.close();
		    	}
				
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if (resultado == null) {
			
			resultado = new ResultadoDTO();
			resultado.setIdPartido(partido.getIdPartido());
			resultado.setIdFase(partido.getIdFase());
			resultado.setIdUsuario(user.getIdUser());
			resultado.setGuardado(false);
		}
		
		return resultado;
	}
	
	/**
	 * Permite crear el resultado de un partido especifico ingresado por un usuario.
	 * @param partido DTO que contiene tanto la informacion del partido como del resultado.
	 * @param user Usuario que ingresa el resultado.
	 */
	public void guardarResultadoPartido(PartidoDTO partido, UsuarioDTO user){
				
		ConexionBD adminConexiones = new ConexionBD();
		Connection con = adminConexiones.getConexion();				
		
	    PreparedStatement pstmt = null;
	    
	    StringBuffer query = new StringBuffer("INSERT INTO RESULTADOS(PARTIDOS_ID_PARTIDO, USUARIOS_DSUSER,");
	    query.append(" PARTIDOS_FASES_IDFASE, GOLES_LOCALPENAL, GOLES_LOCAL, GOLES_VISITANTE, ");
	    query.append(" GOLES_VISITANTEPENAL, PUNTOS_MARCADOR, PUNTOS_RESULTADO)");
	    query.append(" VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
	    
	    try {
		    pstmt = con.prepareStatement(query.toString());
		    
		    pstmt.setInt(1, partido.getIdPartido());
		    pstmt.setString(2, user.getIdUser());
		    pstmt.setInt(3, partido.getIdFase());
		    pstmt.setInt(4, partido.getResultado().getGolesLocalPenal());
		    pstmt.setInt(5, partido.getResultado().getGolesLocal());
		    pstmt.setInt(6, partido.getResultado().getGolesVisitante());
		    pstmt.setInt(7, partido.getResultado().getGolesVisitantePenal());
		    pstmt.setInt(8, partido.getResultado().getPuntosMarcador());
		    pstmt.setInt(9, partido.getResultado().getPuntosResultado());
		    
		    pstmt.execute();
		    con.commit();

	    
	    } catch (SQLException e) {
	    	e.printStackTrace();
  
			try {
			      con.rollback();
			      
			} catch (SQLException ex) {
				  e.printStackTrace();
			}
			  
		} finally { 
				
			//libera todos los recursos.
			try {
				
				if (pstmt != null) {
					pstmt.close();
				}
				
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Permite actualizar el resultado de un partido especifico ingresado por un usuario.
	 * @param partido DTO que contiene tanto la informacion del partido como del resultado.
	 * @param user Usuario que ingresa el resultado.
	 */
	public void actualizarResultadoPartido(PartidoDTO partido, UsuarioDTO user) {
		
		ConexionBD adminConexiones = new ConexionBD();
		Connection con = adminConexiones.getConexion();				
		
	    PreparedStatement pstmt = null;
	    

	    StringBuffer query = new StringBuffer("UPDATE RESULTADOS");
	    query.append(" SET GOLES_LOCALPENAL = ?,");
	    query.append(" GOLES_LOCAL = ?,");
	    query.append(" GOLES_VISITANTE = ?,");
	    query.append(" GOLES_VISITANTEPENAL = ?,");
	    query.append(" PUNTOS_MARCADOR = ?,");
	    query.append(" PUNTOS_RESULTADO = ?");
	    query.append(" WHERE  PARTIDOS_ID_PARTIDO = ?");
	    query.append(" AND USUARIOS_DSUSER = ?");
	    query.append(" AND PARTIDOS_FASES_IDFASE = ?");
	    
	    try {
		    pstmt = con.prepareStatement(query.toString());	    
		    
		    pstmt.setInt(1, partido.getResultado().getGolesLocalPenal());
		    pstmt.setInt(2, partido.getResultado().getGolesLocal());
		    pstmt.setInt(3, partido.getResultado().getGolesVisitante());
		    pstmt.setInt(4, partido.getResultado().getGolesVisitantePenal());
		    pstmt.setInt(5, partido.getResultado().getPuntosMarcador());
		    pstmt.setInt(6, partido.getResultado().getPuntosResultado());
		    pstmt.setInt(7, partido.getIdPartido());
		    pstmt.setString(8, user.getIdUser());
		    pstmt.setInt(9, partido.getIdFase());
		    
		    pstmt.executeUpdate();
		    con.commit();
	    
	    } catch (SQLException e) {
	    	e.printStackTrace();
  
			try {
			      con.rollback();
			      
			} catch (SQLException ex) {
				  e.printStackTrace();
			}
			  
		} finally { 
				
			//libera todos los recursos.
			try {
				
				if (pstmt != null) {
					pstmt.close();
				}
				
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Permite eliminar el resultado de un partido especifico ingresado por un usuario.
	 * @param partido DTO que contiene tanto la informacion del partido como del resultado.
	 * @param user Usuario que ingresa el resultado.
	 */
	public void eliminarResultadoPartido(PartidoDTO partido, UsuarioDTO user) {

		ConexionBD adminConexiones = new ConexionBD();
		Connection con = adminConexiones.getConexion();				
		
	    PreparedStatement pstmt = null;
	    
	    StringBuffer query = new StringBuffer("DELETE FROM RESULTADOS");
	    query.append(" WHERE PARTIDOS_ID_PARTIDO = ?");
	    query.append(" AND USUARIOS_DSUSER = ?");
	    query.append(" AND PARTIDOS_FASES_IDFASE = ?");
	    
	    try {
		    pstmt = con.prepareStatement(query.toString());	    
		    
		    pstmt.setInt(1, partido.getIdPartido());
		    pstmt.setString(2, user.getIdUser());
		    pstmt.setInt(3, partido.getIdFase());
		    
		    pstmt.execute();		    
		    con.commit();

	    
	    } catch (SQLException e) {
	    	e.printStackTrace();
  
			try {
			      con.rollback();
			      
			} catch (SQLException ex) {
				  e.printStackTrace();
			}
			  
		} finally { 
				
			//libera todos los recursos.
			try {
				
				if (pstmt != null) {
					pstmt.close();
				}
				
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
